﻿using System;
using System.Collections.Generic;

namespace TTLL.Asm
{

    //要特别适合字节流分析
    public enum OpCode : byte
    {//一个字节，限制256条指令
        End = 0x00,    //最后一条指令，方便结束留下的
        Nop,    //no param no name
        Skip,   //skip some bytes,maybe is comment


        //LOOPS
        If, //If (cond) {block} //條件是個特殊的類型
        Block,  //with label,with subInstructions,block的label怎麽保存？
        //IfBlock,//with var,labelid,with subInstrurction
        Continue,//with  num
        Break,//with  num

        //move
        //給變量或參數賦值的指令 ，參數有ref型，可以外傳值
        Set,//ret = SET v
        MemSet,//内存寫
        MemGet,//内存讀

        //call調用
        Call, //call 函数需要指定call target,这里比较复杂，target的定义写在哪里？在const中或者var中
        Ret,//流程控制


        //math
        //Define,//Type[index] name ,虚拟指令，定义变量，tobytes 不存在，变成function的一部分
        //变量生存期由编译器决定
        Add,//with return var,type,var1 or innum,var2 or innum 
        Sub,//with return var,type,var1 or innum,var2 on innum
        Mul,//with return var,type,_Int32, //with Typ
        Div,//with return var,type

        //bit

        //logic 1
        Zero,
        NotZero,
        //logic 2
        Equal,     //==
        NotEqual,   //!=
        GreatEqual, //>=
        Great,      //
        LessEqual,  //
        Less,       //

        //Call的第一个参数就是函数指针

        PlatformMov,//其他语言的Mov ，主要用来给其他语言寄存器赋值
        PlatformInt,//调用其他语言的Int

        // FunctionRe
    }
    [Flags]
    public enum InstParamType : byte //5bit 类型 ，3字节记录长度
    {//32种
        Unknown = 0x00,

        ImNumber = 0x01,//立即数
        Const = 0x02,//常量引用
        Param = 0x03,//参数引用
        Var = 0x04,//变量引用
        ReturnVar = 0x05,//返回类型
        RefVar = 0x06,//可以被下级函数改变的值类型 
        RefParam = 0x07,//可以被下级函数改变的参数类型

        BlockLayer = 8,//Block引用
        Option = 9,//指令类型，指令使用的其他参数
        PlatformOption = 0x0a,//为某平台使用的指令

        //第五个bit 是 是否是函数指针的标志，你也可以认为这是两部分
        //FuncPoint = 0x10,bit on 5

        //ImNumber_Func = FucnPoint & 0x01,//立即数函数指针
        //Const_Func = FucnPoint & 0x02,//常量函数指针
        //Param_Func = FucnPoint & 0x03,//参数函数指针
        //Var_Func  = FucnPoint & 0x04,//变量函数指针
        //ReturnVar_Func  = FucnPoint & 0x04,//变量函数指针
        //RefVar_Func  = FucnPoint & 0x04,//变量函数指针
        //RefParam_Func  = FucnPoint & 0x04,//变量函数指针
    }//然后使用1个bit来表示数据是短还是长，用之后的四个bit表示数据，短数据就直接是这四个bit，长数据就是这个四个bit表示字节长度，之后读这么多字节
    public class InstParam
    {
        public InstParamType type;
        public bool isFunc = false;
        public byte[] value;//int bit length =0~7 0 = zero 1 2 3 4 = re
        public void Write(System.IO.BinaryWriter writer)
        {
            ushort len = value == null ? (ushort)0 : (ushort)value.Length;
            if (len < 0 && len >= 7)
                throw new Exception("error value len");

            byte btype = (byte)((byte)type & (byte)0x0f);

            if (isFunc)
                btype |= (byte)0x10;

            var b = ToBin.Write5BitTypeAndData(writer, btype, len, value);
            if (!b)
                throw new Exception("write error");
        }
        public void Read(System.IO.BinaryReader reader)
        {
            var b = FromBin.Read5BitTypeAndData(reader, out byte type, out ushort len, out byte[] data);
            if (!b)
                throw new Exception("read error");
            this.isFunc = (type & (byte)0x10) > 0;
            this.type = (InstParamType)(type & 0x0f);
            if (len > 0)
                this.value = data;
        }
    }
    public class Body
    {
        public void Clear()
        {
            body.Clear();
        }
        public Body parent;
        public string BlockLabel;//block的標簽，如果有，每一個block，會從function開始有一個計數器，第一個為1
        public byte BlockDepth = 0;//If 沒有Block深度，所以不可能continue 和 break if 快
        public List<Instruction> body = new List<Instruction>();
        public byte GetMinDepth()
        {
            var body = parent;
            while (body != null)
            {
                if (BlockDepth > 0) return BlockDepth;
                body = body.parent;
            }
            return 0;
        }
    }
    public class Instruction
    {
        static int GetParamCount(OpCode code)
        {
            switch (code) //opcode 只有三种保存形式 无参 一参 多参，block 是唯一一个例外
            {
                case OpCode.Nop://noparam
                case OpCode.End:
                case OpCode.Ret:
                    return 0;
                case OpCode.Skip://1 param
                case OpCode.Continue:
                case OpCode.Break:
                    return 1;
                case OpCode.If:
                case OpCode.Block://multi params and sub instructions
                    return 0xff;//spec
                default://沒特別指定都按多參數算
                    return 2;
            }
        }
        public Body parent;

        public OpCode code;
        public List<InstParam> instParams;
        public Instruction IfCondition;//用一個條件指令作爲if
        //public string BlockLabel;//block的標簽，如果有，每一個block，會從function開始有一個計數器，第一個為1
        //public uint BlockDepth = 0;//If 沒有Block深度，所以不可能continue 和 break if 快
        //public List<Instruction> BlockBody;
        public Body Body;
        public void Write(System.IO.BinaryWriter writer)
        {
            writer.Write((byte)code);
            var pcount = GetParamCount(code);
            if (pcount == 0)
            {
                return;
            }
            else if (pcount == 1)
            {
                instParams[0].Write(writer);
            }
            else if (pcount == 0xff)
            {
                if (code == OpCode.If) //if比block 多一個條件指令
                {
                    IfCondition.Write(writer);
                }
                if (instParams.Count > 0xff)
                    throw new Exception("too mush params");
                writer.Write((byte)instParams.Count);
                for (var i = 0; i < instParams.Count; i++)
                {
                    instParams[i].Write(writer);
                }
                writer.Write((UInt32)Body.body.Count);
                for (var i = 0; i < Body.body.Count; i++)
                {
                    Body.body[i].Write(writer);
                }
            }
            else if (pcount == 2)
            {
                if (instParams.Count > 0xff)
                    throw new Exception("too mush params");
                writer.Write((byte)instParams.Count);
                for (var i = 0; i < instParams.Count; i++)
                {
                    instParams[i].Write(writer);
                }
            }
        }

        public void Read(System.IO.BinaryReader reader)
        {
            this.code = (OpCode)reader.ReadByte();
            var pcount = GetParamCount(code);
            if (pcount == 0)
            {
                return;
            }
            else if (pcount == 1)
            {
                instParams = new List<InstParam>();
                instParams.Add(new InstParam());
                instParams[0].Read(reader);
            }
            else if (pcount == 2)
            {
                if (instParams == null)
                    instParams = new List<InstParam>();
                var count = reader.ReadByte();
                if (instParams.Count > count)
                    instParams.RemoveRange(count, instParams.Count - count);

                for (var i = 0; i < count; i++)
                {
                    if (instParams.Count <= i)
                        instParams.Add(new InstParam());
                    instParams[i].Read(reader);
                }
            }
            else if (pcount == 0xff)
            {
                if (Body == null)
                    Body = new Body();
                else
                    Body.Clear();

                if (code == OpCode.If) //if比block 多一個條件指令
                {
                    IfCondition = new Instruction();
                    IfCondition.Read(reader);
                }
                else
                {//恢復depth屬性
                    byte maxdepth = parent.GetMinDepth();
                    if (maxdepth == 0) maxdepth = 0xff;
                    Body.BlockDepth = (byte)(maxdepth - 1);
                    //嘗試回復label
                }
                if (instParams == null)
                    instParams = new List<InstParam>();
                var count = reader.ReadByte();
                if (instParams.Count < count)
                    instParams.RemoveRange(count, instParams.Count - count);

                for (var i = 0; i < count; i++)
                {
                    if (instParams.Count <= i)
                        instParams.Add(new InstParam());
                    instParams[i].Read(reader);
                }
                var subblockcount = reader.ReadUInt32();

                for (var i = 0; i < subblockcount; i++)
                {
                    var inst = new Instruction();
                    inst.Read(reader);
                    Body.body.Add(inst);
                }
            }
        }

        public static void WriteList(Body body, System.IO.BinaryWriter writer)
        {
            var count = (UInt32)body.body.Count;
            writer.Write(count);
            for (var i = 0; i < count; i++)
            {
                body.body[i].Write(writer);
            }
        }
        public static void ReadList(Body body, System.IO.BinaryReader reader)
        {
            var count = reader.ReadUInt32();
            for (var i = 0; i < count; i++)
            {
                Instruction inst = new Instruction();
                inst.parent = body;
                inst.Read(reader);
                body.body.Add(inst);
            }
        }
    }
    public enum NativeType : byte //只有5bit 可以用 0~31
    {//一个字节，限制256条指令 //扩展一下这个Type,可以加附加选项的
     //这玩意和参数不一样，参数可能有空的，这个不可能有，
     //限制长度5bit ,那么最多32种，右侧3bit 指定附加类型数据长度 000 = 0 001 =1 010 =2 011 =4 100=8 101 =16 110 =after 1byte 111=afer 2byte
        Unknown = 0x00,
        Void = 0x01,
        Byte1 = 0x02,
        Byte2 = 0x03,
        Byte4 = 0x04,
        Byte8 = 0x05,
        ByteArray = 0x06,
        ByteArray_String_ASCII_ZeroEnd, //这些都是string的byte[]形式，弄个结构，只是方便Dump
        ByteArray_String_UTF8_ZeroEnd,
        ByteArray_String_UTF16_ZeroEnd,
        ByteArray_String_UTF32_ZeroEnd,
        Struct = 0x10,//Struct是很有趣的//struct 是bytearray的另一种形式，只是此时他的data 是UInt32 的 StructID,从1开始
                      //动态的去组合这个struct的值
        Ptr16,
        Ptr32,
        Ptr64,
        //Ptr,//指针长度是个临时设计
        Function_ThisModule,//指向本模块中的函数,可以快地址走，立即数只允许使用这种模式
        Function_Dynamic,//指向任何位置模块中的函数，需要查表
    }
    public struct NativeTypeEX
    {
        public NativeType type;
        public byte[] exType;

        public static NativeTypeEX Void => new NativeTypeEX() { type = NativeType.Void, exType = null };
        public static NativeTypeEX Byte4 => new NativeTypeEX() { type = NativeType.Byte4, exType = null };
        public static NativeTypeEX Unknown => new NativeTypeEX() { type = NativeType.Unknown, exType = null };

        public static NativeTypeEX FromString(string text)
        {
            if (text.ToLower() == "byte4")
                return NativeTypeEX.Byte4;
            return default(NativeTypeEX);
        }
        public byte[] DataFromString(string str)
        {
            if (this.type == NativeType.Byte4)
            {
                var data = new byte[4];
                if (str.ToLower().IndexOf("0x") == 0)
                {
                    data = BitConverter.GetBytes(UInt32.Parse(str.Substring(2), System.Globalization.NumberStyles.HexNumber));
                }
                else if (char.IsDigit(str[0]))
                    data = BitConverter.GetBytes(UInt32.Parse(str));

                return data;
            }
            return null;
        }
        public override string ToString()
        {
            return base.ToString();
        }
        public void Write(System.IO.BinaryWriter writer)
        {
            ushort len = 0;
            if (this.exType != null)
                len = (ushort)this.exType.Length;
            var b = ToBin.Write5BitTypeAndData(writer, (byte)this.type, len, this.exType);
            if (!b)
                throw new Exception("write error.");
        }
        public void Read(System.IO.BinaryReader reader)
        {
            var b = FromBin.Read5BitTypeAndData(reader, out byte type, out UInt16 datalen, out byte[] data);
            if (!b)
                throw new Exception("read error.");

            //var data = reader.ReadByte();
            this.type = (NativeType)(type);
            if (datalen > 0)
            {
                this.exType = data;
            }
        }
        //static readonly byte[] convert = new byte[] { 0, 1, 2, 4, 8, 16, //more1byte, //more2byte };

    }

    public class ConstValue
    {
        public NativeTypeEX type;
        public byte[] data;

        public void Write(System.IO.BinaryWriter writer)
        {
            type.Write(writer);
            //writer.Write((byte)type);
            if (data == null)
            {
                writer.Write((UInt16)0);
            }
            else
            {
                writer.Write((UInt16)data.Length);
                writer.Write(data);
            }
        }
        public void Read(System.IO.BinaryReader reader)
        {
            type.Read(reader);
            //type = (NativeType)reader.ReadByte();
            var length = reader.ReadUInt16();
            if (length != 0)
                data = reader.ReadBytes(length);
            else
                data = null;
        }
        public static void WriteList(IList<ConstValue> defines, System.IO.BinaryWriter writer)
        {
            var count = (UInt32)defines.Count;
            writer.Write(count);
            for (var i = 0; i < count; i++)
            {
                defines[i].Write(writer);
            }
        }
        public static void ReadList(IList<ConstValue> defines, System.IO.BinaryReader reader)
        {
            var count = reader.ReadUInt32();
            for (var i = 0; i < count; i++)
            {
                ConstValue _define = new ConstValue();
                _define.Read(reader);
                defines.Add(_define);
            }
        }

    }
    public class VarDefine
    {
        public NativeTypeEX type;
        //public UInt16 length;
        public UInt32 initConstValue;
        public void Write(System.IO.BinaryWriter writer)
        {
            type.Write(writer);
            //writer.Write((byte)type);
            //writer.Write((UInt16)length);
            writer.Write(initConstValue);
        }
        public void Read(System.IO.BinaryReader reader)
        {
            type.Read(reader);
            //type = (NativeType)reader.ReadByte();
            //length = reader.ReadUInt16();
            initConstValue = reader.ReadUInt32();
        }
        public static void WriteList(IList<VarDefine> defines, System.IO.BinaryWriter writer)
        {
            var count = (UInt32)defines.Count;
            writer.Write(count);
            for (var i = 0; i < count; i++)
            {
                defines[i].Write(writer);
            }
        }
        public static void ReadList(IList<VarDefine> defines, System.IO.BinaryReader reader)
        {
            var count = reader.ReadUInt32();
            for (var i = 0; i < count; i++)
            {
                VarDefine _define = new VarDefine();
                _define.Read(reader);
                defines.Add(_define);
            }
        }
    }

    //[AttrOnly]
    //struct abc
    //{
    //
    //}
    //可以使用struct来配置

    //[ID]      语法1.ID nothing 语法 ID 可以是个struct
    //[ID(name1=value[,name2=value[,name3=value]])] //函数调用命名参数语法
    //[ID(name1[,name2[,name3]])] //函数调用顺序参数语法

    //[ID:{a:value,b:value}]//json 对象
    //[ID:123]
    //[ID:"aaabb"]
    public class Attribute
    {
        public string name;//Attribute 只使用名字
                           //这个name可以和一个struct相同，如果使用命名参数语法，则必须定义struct
                           //如果使用顺序参数语法或者无参语法，则不必有对应的struct
        public List<string> values;//params 必须填满，没有就填null
        public void Write(System.IO.BinaryWriter writer)
        {
            var data = System.Text.Encoding.UTF8.GetBytes(name);
            var len = (byte)data.Length;
            writer.Write(len);
            writer.Write(data);
            StringHelper.WriteStringList(values, writer);
        }
        public void Read(System.IO.BinaryReader reader)
        {
            var len = reader.ReadByte();
            var data = reader.ReadBytes(len);
            this.name = System.Text.Encoding.UTF8.GetString(data);
            this.values = new List<string>();
            StringHelper.ReadStringList(values, reader);
        }
        public static void WriteList(IList<Attribute> list, System.IO.BinaryWriter writer)
        {
            UInt32 count = list == null ? (UInt32)0 : (UInt32)list.Count;
            writer.Write(count);
            for (var i = 0; i < count; i++)
            {
                list[i].Write(writer);
            }
        }
        public static void ReadList(IList<Attribute> list, System.IO.BinaryReader reader)
        {
            UInt32 count = reader.ReadUInt32();
            for (var i = 0; i < count; i++)
            {
                Attribute attr = new Attribute();
                attr.Read(reader);
                list.Add(attr);
            }
        }
    }
    public class StringHelper
    {
        public static void WriteStringList(IList<string> list, System.IO.BinaryWriter writer)
        {
            UInt32 count = list == null ? (UInt32)0 : (UInt32)list.Count;
            writer.Write(count);
            for (var i = 0; i < count; i++)
            {
                if (list[i] == null)
                {
                    writer.Write((byte)0);
                }
                else
                {
                    var data = System.Text.Encoding.UTF8.GetBytes(list[i]);
                    var len = (byte)data.Length;
                    writer.Write(len);
                    writer.Write(data);
                }
            }
        }
        public static void ReadStringList(IList<string> list, System.IO.BinaryReader reader)
        {
            UInt32 count = reader.ReadUInt32();
            for (var i = 0; i < count; i++)
            {
                var len = reader.ReadByte();
                var data = reader.ReadBytes(len);
                var name = System.Text.Encoding.UTF8.GetString(data);
                list.Add(name);
            }
        }
    }
    public class Function
    {
        public List<Attribute> attributes;//attribute 用來做一些配置工作
        public List<string> paramNameTable;
        public List<string> varNameTable;
        public List<string> labelNameTable;
        public VarDefine Return;
        public List<VarDefine> Params;  //入参
        public List<VarDefine> Variabes;//内部变量
        public Body Body;
        //public List<Instruction> Body;

        public static Function CreateEmpty()
        {
            var func = new Function();
            func.attributes = new List<Attribute>();
            func.varNameTable = new System.Collections.Generic.List<string>();
            func.labelNameTable = new System.Collections.Generic.List<string>();
            func.paramNameTable = new System.Collections.Generic.List<string>();
            func.Return = new VarDefine();
            func.Params = new System.Collections.Generic.List<VarDefine>();
            func.Variabes = new System.Collections.Generic.List<VarDefine>();
            func.Body = new Body();// System.Collections.Generic.List<Instruction>();
            return func;
        }
        public void Write(System.IO.BinaryWriter writer)
        {
            Attribute.WriteList(attributes, writer);
            Return.Write(writer);
            VarDefine.WriteList(Params, writer);
            VarDefine.WriteList(Variabes, writer);
            Instruction.WriteList(Body, writer);
            StringHelper.WriteStringList(paramNameTable, writer);
            StringHelper.WriteStringList(varNameTable, writer);
            StringHelper.WriteStringList(labelNameTable, writer);
        }

        public void Read(System.IO.BinaryReader reader)
        {
            attributes = new List<Attribute>();
            Attribute.ReadList(attributes, reader);
            Return = new VarDefine();
            Return.Read(reader);
            Params = new List<VarDefine>();
            Variabes = new List<VarDefine>();
            Body = new Body();
            paramNameTable = new List<string>();
            varNameTable = new List<string>();
            labelNameTable = new List<string>();
            VarDefine.ReadList(Params, reader);
            VarDefine.ReadList(Variabes, reader);
            Instruction.ReadList(Body, reader);
            StringHelper.ReadStringList(paramNameTable, reader);
            StringHelper.ReadStringList(varNameTable, reader);
            StringHelper.ReadStringList(labelNameTable, reader);
        }
    }
    //Struct Define in ASM
    public class Struct
    {
        public List<Attribute> attributes;//attribute 用來做一些配置工作
        public List<VarDefine> members;
        public List<string> memberNameTable;
        public static Struct CreateEmpty()
        {
            Struct s = new Struct();
            s.attributes = new List<Attribute>();
            s.members = new List<VarDefine>();
            s.memberNameTable = new List<string>();
            return s;
        }
        public void Write(System.IO.BinaryWriter writer)
        {
            Attribute.WriteList(attributes, writer);
            VarDefine.WriteList(members, writer);
            StringHelper.WriteStringList(memberNameTable, writer);
        }
        public void Read(System.IO.BinaryReader reader)
        {
            attributes = new List<Attribute>();
            members = new List<VarDefine>();
            memberNameTable = new List<string>();
            Attribute.ReadList(attributes, reader);
            VarDefine.ReadList(members, reader);
            StringHelper.ReadStringList(memberNameTable, reader);
        }
        public static void WriteList(IList<Struct> list, System.IO.BinaryWriter writer)
        {
            UInt32 count = list == null ? (UInt32)0 : (UInt32)list.Count;
            writer.Write(count);
            for (var i = 0; i < count; i++)
            {
                list[i].Write(writer);
            }
        }
        public static void ReadList(IList<Struct> list, System.IO.BinaryReader reader)
        {
            UInt32 count = reader.ReadUInt32();
            for (var i = 0; i < count; i++)
            {
                Struct attr = new Struct();
                attr.Read(reader);
                list.Add(attr);
            }
        }
    }
    public class Module
    {
        public List<string> constNameTable;
        public List<string> funcNameTable;
        public List<string> structNameTable;
        public List<ConstValue> constTable;
        public List<Function> funcTable;
        public List<Struct> structTable;
        public static Module CreateEmpty()
        {
            Module module = new Module();
            //这三张表是必须初始化的
            module.funcNameTable = new System.Collections.Generic.List<string>();
            module.funcTable = new System.Collections.Generic.List<Function>();
            module.constTable = new System.Collections.Generic.List<ConstValue>();
            module.structTable = new List<Struct>();
            module.structNameTable = new List<string>();
            module.constNameTable = new List<string>();
            return module;
        }
        public void WriteAll(System.IO.BinaryWriter writer)
        {
            if (constNameTable != null && constNameTable.Count != constTable.Count)
                throw new Exception("error constNameTable count");
            if (funcNameTable.Count != funcTable.Count)
                throw new Exception("error functionNameTable count");
            if (structNameTable.Count != structTable.Count)
                throw new Exception("error structNameTable count");
            //准备const Name表
            byte[] constNameTableData = null;
            if (constNameTable != null)
                using (var ms = new System.IO.MemoryStream())
                {
                    using (var subwriter = new System.IO.BinaryWriter(ms))
                    {
                        var count = (UInt32)constNameTable.Count;
                        subwriter.Write(count);
                        for (var i = 0; i < count; i++)
                        {
                            if (constNameTable[i] == null)
                            {
                                subwriter.Write((byte)0);
                            }
                            else
                            {
                                var data = System.Text.Encoding.UTF8.GetBytes(constNameTable[i]);
                                var len = (byte)data.Length;
                                subwriter.Write(len);
                                subwriter.Write(data);
                            }
                        }
                        constNameTableData = ms.ToArray();
                    }
                }

            //准备const Data
            byte[] constTableData = null;
            using (var ms = new System.IO.MemoryStream())
            {
                using (var subwriter = new System.IO.BinaryWriter(ms))
                {
                    ConstValue.WriteList(constTable, subwriter);
                    constTableData = ms.ToArray();
                }
            }


            //准备function Data
            UInt32[] funcOffset = new UInt32[funcTable.Count];
            byte[] funcTableData = null;
            using (var ms = new System.IO.MemoryStream())
            {
                using (var subwriter = new System.IO.BinaryWriter(ms))
                {
                    var count = (UInt32)funcTable.Count;
                    subwriter.Write(count);
                    for (var i = 0; i < count; i++)
                    {
                        funcOffset[i] = (UInt32)subwriter.BaseStream.Position;
                        funcTable[i].Write(subwriter);
                    }
                    funcTableData = ms.ToArray();
                }
            }

            //准备func 映射表
            byte[] funcMapTableData = null;
            using (var ms = new System.IO.MemoryStream())
            {
                using (var subwriter = new System.IO.BinaryWriter(ms))
                {
                    var count = (UInt32)funcNameTable.Count;
                    subwriter.Write(count);
                    for (var i = 0; i < count; i++)
                    {
                        var data = System.Text.Encoding.UTF8.GetBytes(funcNameTable[i]);
                        var len = (byte)data.Length;
                        subwriter.Write(funcOffset[i]);
                        subwriter.Write(len);
                        subwriter.Write(data);
                    }
                    funcMapTableData = ms.ToArray();
                }
            }

            //准备struct Data
            UInt32[] structOffset = new UInt32[structTable.Count];
            byte[] structTableData = null;
            using (var ms = new System.IO.MemoryStream())
            {
                using (var subwriter = new System.IO.BinaryWriter(ms))
                {
                    var count = (UInt32)structTable.Count;
                    subwriter.Write(count);
                    for (var i = 0; i < count; i++)
                    {
                        structOffset[i] = (UInt32)subwriter.BaseStream.Position;
                        structTable[i].Write(subwriter);
                    }
                    structTableData = ms.ToArray();
                }
            }

            //准备struct 映射表
            byte[] structMapTableData = null;
            using (var ms = new System.IO.MemoryStream())
            {
                using (var subwriter = new System.IO.BinaryWriter(ms))
                {
                    var count = (UInt32)structNameTable.Count;
                    subwriter.Write(count);
                    for (var i = 0; i < count; i++)
                    {
                        var data = System.Text.Encoding.UTF8.GetBytes(structNameTable[i]);
                        var len = (byte)data.Length;
                        subwriter.Write(structOffset[i]);
                        subwriter.Write(len);
                        subwriter.Write(data);
                    }
                    structMapTableData = ms.ToArray();
                }
            }

            //拼接总数据
            var magicdata = System.Text.Encoding.UTF8.GetBytes("TTLL");
            writer.Write(magicdata);
            var repos = (int)writer.BaseStream.Position;//一会儿还得拐回来
            UInt32 OffsetModuleAttr = 0;//预留一个模块属性区
            UInt32 OffsetFuncMapTable = 0;
            UInt32 OffsetFuncTable = 0;
            UInt32 OffsetStructMapTable = 0;
            UInt32 OffsetStructTable = 0;
            UInt32 OffsetConstTable = 0;
            UInt32 OffsetConstNameTable = 0;
            writer.Write(OffsetModuleAttr);//ModuleAttr 的Offset
            writer.Write(OffsetFuncMapTable);//funcOffset 的Offset
            writer.Write(OffsetFuncTable);//funcTable 的偏移
            writer.Write(OffsetStructMapTable);//funcOffset 的Offset
            writer.Write(OffsetStructTable);//funcTable 的偏移
            writer.Write(OffsetConstTable);//funcTable 的偏移
            writer.Write(OffsetConstNameTable);//funcTable 的偏移
            OffsetFuncMapTable = (UInt32)writer.BaseStream.Position;
            writer.Write(funcMapTableData);
            OffsetFuncTable = (UInt32)writer.BaseStream.Position;
            writer.Write(funcTableData);
            OffsetStructMapTable = (UInt32)writer.BaseStream.Position;
            writer.Write(structMapTableData);
            OffsetStructTable = (UInt32)writer.BaseStream.Position;
            writer.Write(structTableData);

            OffsetConstTable = (UInt32)writer.BaseStream.Position;
            writer.Write(constTableData);
            if (constNameTableData != null)
            {
                OffsetConstNameTable = (UInt32)writer.BaseStream.Position;
                writer.Write(constNameTableData);
            }

            writer.Seek(repos, System.IO.SeekOrigin.Begin);
            writer.Write(OffsetModuleAttr);//ModuleAttr 的Offset
            writer.Write(OffsetFuncMapTable);//funcOffset 的Offset
            writer.Write(OffsetFuncTable);//funcTable 的偏移
            writer.Write(OffsetStructMapTable);//funcOffset 的Offset
            writer.Write(OffsetStructTable);//funcTable 的偏移
            writer.Write(OffsetConstTable);//funcTable 的偏移
            writer.Write(OffsetConstNameTable);//funcTable 的偏移

        }
        public void ReadAll(System.IO.BinaryReader reader)
        {
            var magicstr = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(4));
            if (magicstr != "TTLL")
                throw new Exception("error magic str");
            UInt32 OffsetModuleAttr = reader.ReadUInt32();//预留一个模块属性区
            UInt32 OffsetFuncMapTable = reader.ReadUInt32();
            UInt32 OffsetFuncTable = reader.ReadUInt32();
            UInt32 OffsetStructMapTable = reader.ReadUInt32();
            UInt32 OffsetStructTable = reader.ReadUInt32();
            UInt32 OffsetConstTable = reader.ReadUInt32();
            UInt32 OffsetConstNameTable = reader.ReadUInt32();

            //read funcname and functable
            reader.BaseStream.Position = OffsetFuncMapTable;
            {
                var count = reader.ReadUInt32();
                funcNameTable = new List<string>();
                funcTable = new List<Function>();
                for (var i = 0; i < count; i++)
                {
                    var offset = reader.ReadUInt32();
                    var namelen = reader.ReadByte();
                    var data = reader.ReadBytes(namelen);
                    var name = System.Text.Encoding.UTF8.GetString(data);
                    funcNameTable.Add(name);
                    var repos = reader.BaseStream.Position;
                    {//read function
                        var funcpos = OffsetFuncTable + offset;
                        reader.BaseStream.Position = funcpos;
                        var func = new Function();
                        func.Read(reader);
                        funcTable.Add(func);
                    }
                    reader.BaseStream.Position = repos;
                }
            }
            //read structname and functable
            reader.BaseStream.Position = OffsetStructMapTable;
            {
                var count = reader.ReadUInt32();
                structNameTable = new List<string>();
                structTable = new List<Struct>();
                for (var i = 0; i < count; i++)
                {
                    var offset = reader.ReadUInt32();
                    var namelen = reader.ReadByte();
                    var data = reader.ReadBytes(namelen);
                    var name = System.Text.Encoding.UTF8.GetString(data);
                    structNameTable.Add(name);
                    var repos = reader.BaseStream.Position;
                    {//read function
                        var structpos = OffsetStructTable + offset;
                        reader.BaseStream.Position = structpos;
                        var _struct = new Struct();
                        _struct.Read(reader);
                        structTable.Add(_struct);
                    }
                    reader.BaseStream.Position = repos;
                }
            }

            //read consttable
            reader.BaseStream.Position = OffsetConstTable;
            {
                constTable = new List<ConstValue>();
                ConstValue.ReadList(constTable, reader);
            }

            //read constNameTable
            if (OffsetConstNameTable > 0)
            {
                reader.BaseStream.Position = OffsetConstNameTable;
                {
                    var count = reader.ReadUInt32();
                    constNameTable = new List<string>();
                    for (var i = 0; i < count; i++)
                    {
                        var namelen = reader.ReadByte();
                        var data = reader.ReadBytes(namelen);
                        var name = System.Text.Encoding.UTF8.GetString(data);
                        constNameTable.Add(name);
                    }
                }
            }
        }

        public NativeTypeEX GetTypeFromStr(string name)
        {
            if (name == "void" || name == "Void")
            {
                return NativeTypeEX.Void;
            }
            if (name == "byte4")
            {
                return NativeTypeEX.Byte4;
            }
            return NativeTypeEX.Unknown;
        }
        public uint GetConstFromStr(string name)
        {
            int i = this.constNameTable.IndexOf(name) + 1;
            if (i > 0)
            {
                return (uint)i;
            }
            return 0;
        }
    }

}
